package cn.luckdou.commons.pay.wechat;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import cn.luckdou.commons.utils.IDUtils;
import cn.luckdou.commons.utils.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import cn.luckdou.commons.pay.wechat.util.ClientCustomSSL;
import cn.luckdou.commons.pay.wechat.util.DataResult;
import cn.luckdou.commons.pay.wechat.util.HttpXmlUtils;
import cn.luckdou.commons.pay.wechat.util.MD5;
import cn.luckdou.commons.pay.wechat.util.MD5Util;
import cn.luckdou.commons.pay.wechat.util.OrderQueryVo;
import cn.luckdou.commons.pay.wechat.util.Orderquery;
import cn.luckdou.commons.pay.wechat.util.RandCharsUtils;
import cn.luckdou.commons.pay.wechat.util.RefundqueryVo;
import cn.luckdou.commons.pay.wechat.util.RequestHandler;
import cn.luckdou.commons.pay.wechat.util.Unifiedorder;
import cn.luckdou.commons.pay.wechat.util.UnifiedorderResult;
import cn.luckdou.commons.pay.wechat.util.WXSignUtils;
import cn.luckdou.commons.pay.wechat.util.WxRefundResult;
import cn.luckdou.commons.pay.wechat.util.XmlJsonUtil;

/**
 * 微信支付
 * @author XianGuo
 *
 */
public class WechatUtil {
	public static String Key = "f361e5a496fe2ecebfd3743b5b6bd7d3";// 商户平台上的那个KEY
	private static final String appid = "wx845c94c403b3da6c";
	private static final String mch_id = "1481103992";
	private static final String notify_url = "http://admin.partylive.cn/appwxpay/wx_notify_url";
	
	/**
	 * 微信支付签名算法sign
	 * @param characterEncoding
	 * @param parameters
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
		StringBuffer sb = new StringBuffer();
		Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）
		Iterator it = es.iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			String k = (String)entry.getKey();
			Object v = entry.getValue();
			if(null != v && !"".equals(v) 
					&& !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + Key);
		String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
		return sign;
	}
	
	/**
	 * 退款
	 * @param out_trade_no
	 * @return
	 */
	public static DataResult wechatRefund(String out_trade_no) {
		if (StringUtils.isBlank(out_trade_no)) {
			return DataResult.build(500,"参数不能为空");
		}
		DataResult dataResult = orderquery(out_trade_no);
		if (dataResult.getStatus()!=200) {
			return dataResult;
		}
		OrderQueryVo QueryResult=(OrderQueryVo)dataResult.getData();
		if ("NOTPAY".equals(QueryResult.getTrade_state())) {
			return DataResult.error("NOTPAY—未支付");
		}else if ("CLOSED".equals(QueryResult.getTrade_state())) {
			return DataResult.error("CLOSED—已关闭");
		}else if ("REVOKED".equals(QueryResult.getTrade_state())) {
			return DataResult.error("REVOKED—已撤销(刷卡支付)");
		}else if ("USERPAYING".equals(QueryResult.getTrade_state())) {
			return DataResult.error("USERPAYING--用户支付中");
		}else if ("PAYERROR".equals(QueryResult.getTrade_state())) {
			return DataResult.error("PAYERROR--支付失败(其他原因，如银行返回失败)");
		}else if ("REFUND".equals(QueryResult.getTrade_state())) {
			return DataResult.error("REFUND—转入退款");
		}else if ("SUCCESS".equals(QueryResult.getTrade_state())) {
			//return DataResult.error("SUCCESS—支付成功 ");
			// 参数组
			String nonce_str = RandCharsUtils.getRandomString(16);// 随机字符串
			String appsecret = mch_id;
			String op_user_id = mch_id;// 就是MCHID
			String total_fee = QueryResult.getTotal_fee();// 就是MCHID
			String out_refund_no= IDUtils.getOrderNum();
			SortedMap<String, String> packageParams = new TreeMap<String, String>();
			packageParams.put("appid", appid);
			packageParams.put("mch_id", mch_id);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("out_trade_no", out_trade_no);
			packageParams.put("out_refund_no", out_refund_no);
			packageParams.put("total_fee", total_fee);
			packageParams.put("refund_fee", total_fee);
			packageParams.put("op_user_id", op_user_id);
			RequestHandler reqHandler = new RequestHandler(null, null);
			reqHandler.init(appid, appsecret, Key);
			String sign = reqHandler.createSign(packageParams);
			String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>" + "<nonce_str>"
					+ nonce_str + "</nonce_str>" + "<sign><![CDATA[" + sign + "]]></sign>" + "<out_trade_no>" + out_trade_no
					+ "</out_trade_no>" + "<out_refund_no>" + out_refund_no + "</out_refund_no>" + "<total_fee>" + total_fee
					+ "</total_fee>" + "<refund_fee>" + total_fee + "</refund_fee>" + "<op_user_id>" + op_user_id
					+ "</op_user_id>" + "</xml>";
			String createOrderURL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
			try {
				String s = ClientCustomSSL.doRefund(createOrderURL, xml);
				String json = XmlJsonUtil.xml2JSON(s);
				WxRefundResult result = JsonUtils.jsonToPojo(json, WxRefundResult.class);
				//System.out.println(result);
				if ("SUCCESS".equals(result.getReturn_code()) && "SUCCESS".equals(result.getResult_code())) {
					return DataResult.ok(result);
				} else {
					return DataResult.build(500, result.getErr_code_des());
				}
			} catch (Exception e) {
				e.printStackTrace();
				return DataResult.build(500, e.getMessage());
			}
		}else {
			return DataResult.error("订单信息状态错误!");
		}
		
		
	}

	/**
	 * 查询订单
	 * @param out_trade_no
	 * @return
	 */
	public static DataResult orderquery(String out_trade_no) {
		// 参数组
		String nonce_str = RandCharsUtils.getRandomString(16);// 随机字符串
		// 参数：开始生成签名
		SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
		parameters.put("appid", appid);
		parameters.put("mch_id", mch_id);
		parameters.put("nonce_str", nonce_str);
		parameters.put("out_trade_no", out_trade_no);
		String sign = createSign("UTF-8", parameters);
		Orderquery orderquery = new Orderquery();
		orderquery.setAppid(appid);
		orderquery.setMch_id(mch_id);
		orderquery.setOut_trade_no(out_trade_no);
		orderquery.setNonce_str(nonce_str);
		orderquery.setSign(sign);
		// 构造xml参数
		String xmlInfo = XmlJsonUtil.json2XML(JsonUtils.toJson(orderquery));
		String wxUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
		String method = "POST";
		String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
		String json = XmlJsonUtil.xml2JSON(weixinPost);
		//System.out.println(json);
		OrderQueryVo woqr = JsonUtils.jsonToPojo(json, OrderQueryVo.class);
		if ("SUCCESS".equals(woqr.getReturn_code())) {
			if ("SUCCESS".equals(woqr.getResult_code())) {
				return DataResult.ok(woqr);
			} else {
				return DataResult.build(500, woqr.getErr_code_des());
			}
		}
		return DataResult.build(500, woqr.getReturn_msg());

	}
	
	/**
	 * 查询退款
	 * @param out_trade_no
	 * @return
	 */
	public static DataResult refundquery(String out_trade_no) {
		// 参数组
		String nonce_str = RandCharsUtils.getRandomString(16);// 随机字符串
		// 参数：开始生成签名
		SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
		parameters.put("appid", appid);
		parameters.put("mch_id", mch_id);
		parameters.put("nonce_str", nonce_str);
		parameters.put("out_trade_no", out_trade_no);
		String sign = WXSignUtils.createSign("UTF-8", parameters);
		Orderquery orderquery = new Orderquery();
		orderquery.setAppid(appid);
		orderquery.setMch_id(mch_id);
		orderquery.setOut_trade_no(out_trade_no);
		orderquery.setNonce_str(nonce_str);
		orderquery.setSign(sign);
		// 构造xml参数
		String xmlInfo = XmlJsonUtil.json2XML(JsonUtils.toJson(orderquery));
		String wxUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
		String method = "POST";
		String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
		String json = XmlJsonUtil.xml2JSON(weixinPost);
		//System.out.println(json);
		RefundqueryVo woqr = JsonUtils.jsonToPojo(json, RefundqueryVo.class);
		if ("SUCCESS".equals(woqr.getReturn_code())) {
			if ("SUCCESS".equals(woqr.getResult_code())) {
				return DataResult.ok(woqr);
			} else {
				return DataResult.build(500, woqr.getResult_code());
			}
		}
		return DataResult.build(500, woqr.getReturn_msg());
		
	}

	public static Long changeY2F(String amount) {
		String currency = amount.replaceAll("\\$|\\￥|\\,", ""); // 处理包含, ￥
																// 或者$的金额
		int index = currency.indexOf(".");
		int length = currency.length();
		Long amLong = 0l;
		if (index == -1) {
			amLong = Long.valueOf(currency + "00");
		} else if (length - index >= 3) {
			amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
		} else if (length - index == 2) {
			amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
		} else {
			amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
		}
		return amLong;
	}
	
	/**
	 * 预下订单
	 * 
	 * @time : 2016年12月15日 下午1:44:03
	 * @author: XianGuo
	 * @param out_trade_no
	 *            订单号
	 * @param total_fee
	 *            金额(分)
	 * @return
	 */
	public static UnifiedorderResult preOrder(String out_trade_no, int total_fee) {
		total_fee=total_fee*100;
		// 参数组
		String nonce_str = RandCharsUtils.getRandomString(16);// 随机字符串
		String body = "partylive金币充值";
		String detail = "";
		String attach = "";
		String spbill_create_ip = "127.0.0.1";
		String time_start = RandCharsUtils.timeStart();
		String time_expire = RandCharsUtils.timeExpire();
		String trade_type = "APP";

		// 参数：开始生成签名
		SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
		parameters.put("appid", appid);
		parameters.put("mch_id", mch_id);
		parameters.put("nonce_str", nonce_str);
		parameters.put("body", body);
		parameters.put("nonce_str", nonce_str);
		parameters.put("detail", detail);
		parameters.put("attach", attach);
		parameters.put("out_trade_no", out_trade_no);
		parameters.put("total_fee",total_fee);
		parameters.put("time_start", time_start);
		parameters.put("time_expire", time_expire);
		parameters.put("notify_url", notify_url);
		parameters.put("trade_type", trade_type);
		parameters.put("spbill_create_ip", spbill_create_ip);

		String sign = createSign("UTF-8", parameters);
		Unifiedorder unifiedorder = new Unifiedorder();
		unifiedorder.setAppid(appid);
		unifiedorder.setMch_id(mch_id);
		unifiedorder.setNonce_str(nonce_str);
		unifiedorder.setSign(sign);
		unifiedorder.setBody(body);
		unifiedorder.setDetail(detail);
		unifiedorder.setAttach(attach);
		unifiedorder.setOut_trade_no(out_trade_no);
		unifiedorder.setTotal_fee(total_fee);
		unifiedorder.setSpbill_create_ip(spbill_create_ip);
		unifiedorder.setTime_start(time_start);
		unifiedorder.setTime_expire(time_expire);
		unifiedorder.setNotify_url(notify_url);
		unifiedorder.setTrade_type(trade_type);

		// 构造xml参数
		String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);
		String wxUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		String method = "POST";
		String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
		//System.out.println(weixinPost);
		String json = XmlJsonUtil.xml2JSON(weixinPost);
		UnifiedorderResult unifiedorderResult = JsonUtils.jsonToPojo(json, UnifiedorderResult.class);
		long timestamp = Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10));
		unifiedorderResult.setTimestamp(timestamp);
		unifiedorderResult.setSign(dualSignature(unifiedorderResult));
		return unifiedorderResult;
	}

	/**
	 * 二次签名
	 * 
	 * @time : 2016年12月15日 下午1:44:46
	 * @author: XianGuo
	 * @param unifiedorderResult
	 * @return
	 */
	public static String dualSignature(UnifiedorderResult unifiedorderResult) {
		List<NameValuePair> signParams = new LinkedList<NameValuePair>();
		signParams.add(new BasicNameValuePair("appid", unifiedorderResult.getAppid()));
		signParams.add(new BasicNameValuePair("noncestr", unifiedorderResult.getNonce_str()));
		signParams.add(new BasicNameValuePair("package", "Sign=WXPay"));
		signParams.add(new BasicNameValuePair("partnerid", unifiedorderResult.getMch_id()));
		signParams.add(new BasicNameValuePair("prepayid", unifiedorderResult.getPrepay_id()));
		signParams.add(new BasicNameValuePair("timestamp", unifiedorderResult.getTimestamp() + ""));
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < signParams.size(); i++) {
			sb.append(signParams.get(i).getName());
			sb.append('=');
			sb.append(signParams.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(WXSignUtils.Key);

		String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
		return appSign;
	}

	public static void main(String[] args) {
		//退款成功 {"return_code":"SUCCESS","return_msg":"OK","appid":"wxa03c653bcd16441a","mch_id":"1390106602","nonce_str":"EB6gzhJJi8WCzYVh","sign":"E826AE5E270279BECB681DE01E6D1865","result_code":"SUCCESS","openid":"oL6iOwEmzgl5kLDd9gOm5B5bO2S4","is_subscribe":"N","trade_type":"APP","bank_type":"CCB_DEBIT","total_fee":"5900","fee_type":"CNY","transaction_id":"4001872001201705242370936887","out_trade_no":"201705241631535213160","attach":[],"time_end":"20170524163220","trade_state":"REFUND","cash_fee":"5900","trade_state_desc":"订单发生过退款，退款详情请查询退款单"}
		// DataResult result = wechatRefund(IDUtils.genId(),
		// "201705261639201420965", 1);
		//DataResult dataResult1 = orderquery("201705261639201420965");
		//System.out.println(dataResult1.getData());
//		DataResult dataResult = refundquery("201705261639201420965");
	//	System.out.println(dataResult);
		UnifiedorderResult result = preOrder(IDUtils.getOrderNum(), 30);
		System.out.println(JsonUtils.objectToJson(result).replaceAll(" ", ""));

	}
}
